package com.sky.service.impl;


import cn.hutool.core.bean.BeanUtil;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.constant.UserConstant;
import com.sky.context.BaseContext;
import com.sky.dto.UserLoginDTO;
import com.sky.dto.UserThredDTO;
import com.sky.exception.BaseException;
import com.sky.mapper.UserMapper;
import com.sky.properties.JwtProperties;
import com.sky.properties.WeChatLoginProperties;
import com.sky.result.Result;
import com.sky.service.IUserService;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.sky.entity.User;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;

/**
 * <p>
 * 用户信息 服务实现类
 * </p>
 *
 * @author xieminghui
 * @since 2023-11-16
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private WeChatLoginProperties weChatLoginProperties;
    @Resource
    private JwtProperties jwtProperties;

    @Override
    public Result<UserLoginVO> login(UserLoginDTO userLoginDTO) {
        // 定义方法封装code,小程序id.秘钥,请求类型等参数用于http请求的请求参数
        HashMap<String, String> paramMap = getParamMap(userLoginDTO);
        // 定义方法向微信接口服务获取用户唯一标识openid,参数:get请求字符串参数map集合
        String openId = getOpenId(paramMap);
        // 根据用户唯一标识openid查找数据库,判断是否注册,未注册自动注册
        User user = lambdaQuery().eq(User::getOpenid, openId).one();
        if (BeanUtil.isEmpty(user)) {
            // 用户未注册,自动注册
            log.info("用户未注册,自动注册");
            user = User.builder()
                    .openid(openId)
                    .name(IdUtil.simpleUUID())
                    .createTime(LocalDateTime.now())
                    .build();
            if (!save(user)){
                // 注册失败
                log.info("注册失败");
                throw new BaseException(MessageConstant.REGISTRA_FAILED);
            }
            log.info("注册成功");
        }
        Long userId = user.getId();
        // 设置令牌携带数据
        HashMap<String, Object> userMap = new HashMap<>();
        userMap.put(JwtClaimsConstant.ID, userId);
        // 生成JWT令牌
        String userJwt = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), userMap);
        UserLoginVO userLoginVO = new UserLoginVO(userId, openId, userJwt);
        log.info("返回的对象数据:{}", userLoginVO);
        // 保存到线程空间中
        BaseContext.setCurrentId(new UserThredDTO(userId));
        return Result.success(userLoginVO);
    }

    /**
     * 定义方法向微信接口服务获取用户唯一标识openid,参数:get请求字符串参数map集合
     *
     * @author: XieMingHui
     * @param: [paramMap]
     * @return: java.lang.String
     **/
    private String getOpenId(HashMap<String, String> paramMap) {
        // 请求路径url
        String url = weChatLoginProperties.getUrl();
        log.info("请求参数:{},{}", paramMap, url);
        // 通过授权码,小程序id,小程序秘钥,请求微信接口服务:GET https://api.weixin.qq.com/sns/jscode2session
        String response = HttpClientUtil.doGet(url, paramMap);
        // 解析响应
        JSONObject jsonObject = JSONUtil.parseObj(response);
        String openId = jsonObject.getStr(UserConstant.OPEN_ID);
        if (StrUtil.isBlank(openId)) {
            throw new BaseException(MessageConstant.LOGIN_FAILED);
        }
        // 接受返回的session_key openId 微信用户唯一标识
        return openId;
    }

    /**
     * 定义方法封装code,小程序id.秘钥,请求类型等参数用于http请求的请求参数
     *
     * @author: XieMingHui
     * @param: [userLoginDTO]
     * @return: java.util.HashMap<java.lang.String, java.lang.String>
     **/
    private HashMap<String, String> getParamMap(UserLoginDTO userLoginDTO) {
        log.info("前端的微信授权码:{}", userLoginDTO);
        if (userLoginDTO == null) {
            throw new BaseException(MessageConstant.LOGIN_FAILED);
        }
        // 授权码
        String js_code = userLoginDTO.getCode();
        // 小程序id
        String appid = weChatLoginProperties.getAppid();
        // 小程序秘钥
        String secret = weChatLoginProperties.getSecret();
        // 小程序请求类型code类
        String grant_type = weChatLoginProperties.getGrantType();

        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("js_code", js_code);
        paramMap.put("appid", appid);
        paramMap.put("secret", secret);
        paramMap.put("grant_type", grant_type);
        return paramMap;
    }
}
